/**
 * @file midi2_ump.c
 * @brief MIDI 2.0 UMP消息解析器实现
 * @details 解析MIDI 2.0 UMP格式消息，提取关键参数
 * @version 1.0
 * @date 2025-11-04
 */

#include "midi2_ump.h"
#include <string.h>

/* ============================================================================
 * 私有函数声明
 * ============================================================================ */
static int parse_mt2_midi1_channel(uint8_t *data, uint8_t len, midi2_message_t *msg2);
static int parse_mt4_midi2_channel(uint8_t *data, uint8_t len, midi2_message_t *msg2);

/* ============================================================================
 * 公共函数实现
 * ============================================================================ */

/**
 * @brief 获取UMP消息大小
 */
uint8_t midi2_ump_get_size(uint8_t mt)
{
    switch (mt)
    {
        case UMP_MT_UTILITY:        /* MT0 */
        case UMP_MT_SYSTEM:         /* MT1 */
            return UMP_SIZE_32BIT;

        case UMP_MT_MIDI1_CHANNEL:  /* MT2 */
        case UMP_MT_DATA:           /* MT3 */
            return UMP_SIZE_64BIT;

        case UMP_MT_MIDI2_CHANNEL:  /* MT4 */
        case UMP_MT_EXTENDED_DATA:  /* MT5 */
        case UMP_MT_FLEX_DATA:      /* MTD */
        case UMP_MT_STREAM:         /* MTF */
            return UMP_SIZE_128BIT;

        default:
            return 0;  /* 未知类型 */
    }
}

/**
 * @brief 验证UMP数据包有效性
 */
int midi2_ump_validate(uint8_t *data, uint8_t len)
{
    /* 检查空指针 */
    if (data == NULL || len < UMP_SIZE_32BIT)
    {
        return 0;
    }

    /* 检查长度是否为4的倍数 */
    if (len % 4 != 0)
    {
        return 0;
    }

    /* 提取Message Type */
    uint8_t mt = (data[0] >> 4) & 0x0F;

    /* 验证长度是否匹配MT */
    uint8_t expected_size = midi2_ump_get_size(mt);
    if (expected_size == 0 || len < expected_size)
    {
        return 0;
    }

    return 1;  /* 有效 */
}

/**
 * @brief 解析UMP数据包
 */
int midi2_ump_parse(uint8_t *data, uint8_t len, midi2_message_t *msg2)
{
    /* 参数检查 */
    if (data == NULL || msg2 == NULL)
    {
        return -1;
    }

    /* 验证UMP有效性 */
    if (!midi2_ump_validate(data, len))
    {
        return -1;
    }

    /* 清零输出结构体 */
    memset(msg2, 0, sizeof(midi2_message_t));

    /* 提取Message Type和Group */
    msg2->mt = (data[0] >> 4) & 0x0F;
    msg2->group = data[0] & 0x0F;

    /* 根据MT类型分发解析 */
    switch (msg2->mt)
    {
        case UMP_MT_MIDI1_CHANNEL:  /* MIDI 1.0 in UMP (64位) */
            return parse_mt2_midi1_channel(data, len, msg2);

        case UMP_MT_MIDI2_CHANNEL:  /* MIDI 2.0通道语音 (128位) */
            return parse_mt4_midi2_channel(data, len, msg2);

        case UMP_MT_UTILITY:        /* 暂不支持 */
        case UMP_MT_SYSTEM:
        case UMP_MT_DATA:
        case UMP_MT_EXTENDED_DATA:
        case UMP_MT_FLEX_DATA:
        case UMP_MT_STREAM:
        default:
            return -1;  /* 不支持的消息类型 */
    }
}

/* ============================================================================
 * 私有函数实现
 * ============================================================================ */

/**
 * @brief 解析MT2 (MIDI 1.0通道语音消息 in UMP)
 * @details 格式: [MT(4bit)][Group(4bit)][Status(8bit)][Data1(8bit)]
 *                 [Data2(8bit)][Reserved(24bit)]
 */
static int parse_mt2_midi1_channel(uint8_t *data, uint8_t len, midi2_message_t *msg2)
{
    /* 验证长度 */
    if (len < UMP_SIZE_64BIT)
    {
        return -1;
    }

    /* 提取字段 */
    msg2->status = data[1];
    uint8_t data1 = data[2];
    uint8_t data2 = data[3];

    /* 提取通道 (低4位) */
    msg2->channel = msg2->status & 0x0F;
    uint8_t status_type = msg2->status & 0xF0;

    /* 根据状态类型解析 */
    switch (status_type)
    {
        case 0x80:  /* Note Off */
        case 0x90:  /* Note On */
            msg2->note = data1;
            msg2->velocity_16 = (uint16_t)data2 << 9;  /* 7位转16位: 左移9位 */
            break;

        case 0xB0:  /* Control Change */
            msg2->controller_32 = ((uint32_t)data2) << 25;  /* 7位转32位: 左移25位 */
            break;

        case 0xE0:  /* Pitch Bend */
            /* 14位Pitch Bend转32位: (MSB << 7 | LSB) << 18 */
            msg2->data_16 = ((uint16_t)data2 << 7) | data1;
            break;

        default:
            break;
    }

    return 0;
}

/**
 * @brief 解析MT4 (MIDI 2.0通道语音消息)
 * @details 格式: Word0 [MT(4bit)][Group(4bit)][Status(4bit)][Channel(4bit)][Note(8bit)][Attr Type(8bit)]
 *                 Word1 [Velocity(16bit)][Attr Data(16bit)]
 *                 Word2-3 保留
 */
static int parse_mt4_midi2_channel(uint8_t *data, uint8_t len, midi2_message_t *msg2)
{
    /* 验证长度 */
    if (len < UMP_SIZE_128BIT)
    {
        return -1;
    }

    /* Word 0 解析 */
    uint8_t status_nibble = (data[1] >> 4) & 0x0F;
    msg2->channel = data[1] & 0x0F;
    msg2->note = data[2];
    msg2->attr_type = data[3];

    /* 重建完整状态字节 */
    msg2->status = (status_nibble << 4) | msg2->channel;

    /* Word 1 解析 */
    msg2->velocity_16 = ((uint16_t)data[4] << 8) | data[5];
    msg2->attr_data = ((uint16_t)data[6] << 8) | data[7];

    /* Word 2-3 (保留, 暂不使用) */
    /* data[8-15] reserved */

    /* 根据状态类型提取特定字段 */
    uint8_t status_type = status_nibble << 4;
    switch (status_type)
    {
        case MIDI2_STATUS_NOTE_OFF:
        case MIDI2_STATUS_NOTE_ON:
            /* velocity_16和attr已提取 */
            break;

        case MIDI2_STATUS_CONTROL_CHANGE:
            /* 32位控制器值 (Word 1全32位) */
            msg2->controller_32 = ((uint32_t)data[4] << 24) |
                                  ((uint32_t)data[5] << 16) |
                                  ((uint32_t)data[6] << 8) |
                                  data[7];
            break;

        case MIDI2_STATUS_PITCH_BEND:
            /* 32位Pitch Bend (Word 1全32位) */
            msg2->data_16 = ((uint16_t)data[4] << 8) | data[5];
            break;

        default:
            break;
    }

    return 0;
}
